package service

import (
	"errors"
	"gin_gorm_oj/define"
	"gin_gorm_oj/helper"
	"gin_gorm_oj/model"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"log"
	"net/http"
	"strconv"
	"time"
)

// GetUserDetail
// @Tags 公共方法
// @Summary 用户详情
// @Param user_id query int false "user_id"
// @Success 200 {string} json "{"code":"200","msg","","data":""}"
// @Router /userDetail [get]
func GetUserDetail(c *gin.Context) {
	id := c.Query("user_id")
	if id == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "user_id不能为空",
			"data": "",
		})
		return
	}
	user := new(model.User)
	err := model.DB.Where("id = ?", id).First(&user).Error
	if err != nil {
		log.Println("GetUserDetail err:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "获取用户失败",
			"data": "",
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "success",
		"data": user,
	})
}

// Login
// @Tags 公共方法
// @Summary 用户登录
// @Param username formData string true "username"
// @Param password formData string true "password"
// @Success 200 {string} json "{"code":"200","msg","","data":""}"
// @Router /login [post]
func Login(c *gin.Context) {
	username := c.PostForm("username")
	password := c.PostForm("password")
	if username == "" || password == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "用户名或密码不能为空",
			"data": "",
		})
		return
	}
	password = helper.GetMd5(password)
	//print(username, password)

	date := new(model.User)
	err := model.DB.Where("name = ? AND password = ?", username, password).First(&date).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			c.JSON(http.StatusOK, gin.H{
				"code": -1,
				"msg":  "用户名或密码错误",
			})
			return
		}
		log.Println("Login err:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "登录失败",
		})
		return
	}
	token, err := helper.TestGenerateToken(strconv.Itoa(int(date.ID)), date.Name, date.IsAdmin)
	if err != nil {
		log.Println("Login err:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "登录失败",
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code":  200,
		"msg":   "success",
		"token": token,
	})
}

// SendEmail
// @Tags 公共方法
// @Summary 发送验证码
// @Param email formData string true "email"
// @Success 200 {string} json "{"code":"200","msg","","data":""}"
// @Router /sendEmail [post]
func SendEmail(c *gin.Context) {
	email := c.PostForm("email")
	if email == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数不正确",
		})
		return
	}
	code := helper.GetCode()
	model.RDB.Set(c, email, code, time.Minute*5).Err()
	err := helper.SendEmail(email, code)
	if err != nil {
		log.Println("SendEmail err:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "发送失败" + err.Error(),
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "验证码发送给成功",
	})
}

// Register
// @Tags 公共方法
// @Summary 用户注册
// @Param username formData string true "username"
// @Param password formData string true "password"
// @Param email formData string true "email"
// @Param code formData string true "code"
// @Param phone formData string false "phone"
// @Success 200 {string} json "{"code":"200","msg","","data":""}"
// @Router /register [post]
func Register(c *gin.Context) {
	username := c.PostForm("username")
	password := c.PostForm("password")
	email := c.PostForm("email")
	code := c.PostForm("code")
	phone := c.PostForm("phone")
	if username == "" || password == "" || email == "" || code == "" {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "参数不正确",
		})
		return
	}
	password = helper.GetMd5(password)
	sysCode, err := model.RDB.Get(c, email).Result()
	if err != nil {
		log.Println("Register err:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "注册失败:验证码获取异常" + err.Error(),
		})
		return
	}
	if sysCode != code {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "验证码错误",
		})
		return
	}

	// 判断邮箱是否存在
	var count int64
	err = model.DB.Model(&model.User{}).Where("mail = ?", email).Count(&count).Error
	if err != nil {
		log.Println("Register err:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "查询邮箱异常:" + err.Error(),
		})
		return
	}
	if count > 0 {
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "注册失败:该邮箱已存在",
		})
		return
	}
	user := &model.User{
		Uuid:     helper.GetUUID(),
		Name:     username,
		Password: password,
		Email:    email,
		Phone:    phone,
	}
	err = model.DB.Create(&user).Error
	if err != nil {
		log.Println("Register err:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "注册失败:" + err.Error(),
		})
		return
	}

	// 注册成功返回token
	token, err := helper.TestGenerateToken(user.Uuid, user.Name, user.IsAdmin)
	if err != nil {
		log.Println("Register err:", err)
		c.JSON(http.StatusOK, gin.H{
			"code": -1,
			"msg":  "注册失败:" + err.Error(),
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code":  200,
		"msg":   "success",
		"token": token,
		"uuid":  user.Uuid,
	})
}

// GetRankList
// @Tags 公共方法
// @Summary 用户排行榜
// @Param page query int false "page"
// @Param size query int false "size"
// @Success 200 {string} json "{"code":"200","msg","","data":""}"
// @Router /rankList [get]
func GetRankList(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", define.DefaultPage))
	size, _ := strconv.Atoi(c.DefaultQuery("size", define.DefaultPageSize))
	list := make([]*model.User, 0)
	var count int64
	err := model.DB.Model(new(model.User)).Order("finish_problem_num desc,submit_num desc").Count(&count).Offset((page - 1) * size).Limit(size).Find(&list).Error
	if err != nil {
		log.Println("GetRankList err:", err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": 200,
		"msg":  "success",
		"data": gin.H{
			"list":  list,
			"count": count,
		},
	})
}
